package com.llb666.e.shop.api.controller;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.llb666.e.shop.api.vo.CarouselVo;
import com.llb666.e.shop.api.vo.CategoryVo;
import com.llb666.e.shop.api.vo.NewItemsVo;
import com.llb666.e.shop.api.vo.SimpleCategoryVo;
import com.llb666.e.shop.domain.service.CarouselService;
import com.llb666.e.shop.domain.service.CategoryService;
import com.llb666.e.shop.infracore.config.RedisOperator;
import com.llb666.e.shop.infracore.enums.YesOrNo;
import com.llb666.e.shop.infracore.web.DataResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author llb666
 */
@RestController
@Tag(name = "首页展示相关的接口")
@RequestMapping("/index")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class IndexController {

    private final CarouselService carouselService;
    private final CategoryService categoryService;
    /**
     * 缓存的是Vo,应该在 controller 层做处理
     */
    private final RedisOperator redisOperator;

    @Operation(summary = "获取首页轮播图列表")
    @GetMapping("/carousel")
    public DataResponse<List<CarouselVo>> carousel() {
        List<CarouselVo> list;
        String carouselStr = redisOperator.get("carousel");
        if (StringUtils.isNotBlank(carouselStr)) {
            list = JSON.parseArray(carouselStr, CarouselVo.class);
        } else {
            // 没有从缓存中获取到数据，查询数据库。
            list = CarouselVo.Converter.INSTANCE.do2VoList(carouselService.queryAll(YesOrNo.YES.type));
            if (CollectionUtils.isEmpty(list)) {
                redisOperator.set("carousel", JSONObject.toJSONString(list), 5 * 60);
            } else {
                redisOperator.set("carousel", JSONObject.toJSONString(list));
            }
        }
        return DataResponse.ok(list);
    }

    @Operation(summary = "查询一级商品类目")
    @GetMapping("/cats")
    public DataResponse<List<SimpleCategoryVo>> category() {
        List<SimpleCategoryVo> list;
        String catsStr = redisOperator.get("cats");
        if (StringUtils.isNotBlank(catsStr)) {
            list = JSON.parseArray(catsStr, SimpleCategoryVo.class);
        } else {
            list = SimpleCategoryVo.Converter.INSTANCE.do2VoList(categoryService.queryAllCategoryRoot());
            if (CollectionUtils.isEmpty(list)) {
                redisOperator.set("cats", JSONObject.toJSONString(list), 5 * 60);
            } else {
                redisOperator.set("cats", JSONObject.toJSONString(list));
            }
        }
        return DataResponse.ok(list);
    }

    @Operation(summary = "查询二级子分类商品类目")
    @GetMapping("/subCat/{rootCatId}")
    public DataResponse<List<CategoryVo>> subCategory(
            @Parameter(name = "rootCatId", description = "一级类目id", required = true)
            @PathVariable Integer rootCatId) {
        if (rootCatId == null) {
            return DataResponse.errorMsg("分类不存在！");
        }
        List<CategoryVo> subCatList;
        String subCatStr = redisOperator.get("subCat:" + rootCatId);
        if (StringUtils.isBlank(subCatStr)) {
            subCatList = categoryService.getSubCatList(rootCatId);
            /*
             * 查询的key不存在
             * 对应的id数据库也不存在
             * 此时被非法用户进行攻击，大量的请求穿透到数据库db上
             * 造成宕机，从而影响整个系统，称之为缓存穿透现象
             * 解决方案： 把空的数据也缓存起来，比如空字符串，空对象，空数组
             */
            if (CollectionUtils.isEmpty(subCatList)) {
                //当数据库位空也缓存起来，并设置缓存时间5分钟
                redisOperator.set("subCat:" + rootCatId, JSONObject.toJSONString(subCatList), 5 * 60);
            } else {
                redisOperator.set("subCat:" + rootCatId, JSONObject.toJSONString(subCatList));
            }
        } else {
            subCatList =  JSON.parseArray(subCatStr, CategoryVo.class);
        }
        return DataResponse.ok(subCatList);
    }

    @Operation(summary = "首页滚动加载商品推荐")
    @GetMapping("/sixNewItems/{rootCatId}")
    public DataResponse<List<NewItemsVo>> sixNewItems(
            @Parameter(name = "rootCatId", description = "一级类目id", required = true)
            @PathVariable Integer rootCatId) {
        if (rootCatId == null) {
            return DataResponse.errorMsg("分类不存在！");
        }
        List<NewItemsVo> sixNewItemsLazy;
        String sixNewItemsStr = redisOperator.get("sixNewItems:" + rootCatId);
        if (StringUtils.isBlank(sixNewItemsStr)) {
            sixNewItemsLazy = categoryService.getSixNewItemsLazy(rootCatId);
            if (CollectionUtils.isEmpty(sixNewItemsLazy)) {
                redisOperator.set("sixNewItems:" + rootCatId,  JSONObject.toJSONString(sixNewItemsLazy), 5 * 60);
            } else {
                redisOperator.set("sixNewItems:" + rootCatId, JSONObject.toJSONString(sixNewItemsLazy));
            }
        } else {
            sixNewItemsLazy = JSON.parseArray(sixNewItemsStr, NewItemsVo.class);
        }
        return DataResponse.ok(sixNewItemsLazy);
    }
}
